/**
**********************************************************************
*   Copyright (C) 2021 wy1107412334@163.com All rights reserved.
*
* @file     double_link_list.h
* @brief    对文件的简要说明
* @details  对文件的详细说明
* @author   jcai
* @Version  v0.0.1
* @date     2021-05-17 15:27:32
*
*   Email:  wy1107412334@163.com
*   Blog:   None
*   Github: https://github.com/wy1107412334
*   Gitee:  https://gitee.com/git.git1107412334.com
*
**********************************************************************
@verbatim
@endverbatim
**********************************************************************
* @note
* None.
**********************************************************************
* @attention
* None.
**********************************************************************
* @par 历史记录
*  1. V0.0.1: jcai, 2021-05-17 15:27:32
*    - 首次编写
*  2. V0.0.2: jcai, 2021年5月18日 20点39分
*    - 新增三个函数
*  3. V0.0.3: jcai, 2021年5月19日 19点07分
*    - 修改寻找链表中指定节点的函数及其回调函数的参数表
*  4. V0.0.4: jcai, 2021年5月31日 13点30分
*    - 定义枚举值作为函数返回的错误码
*    - 定义遍历链表的宏
*
**********************************************************************
*/

#ifndef __DOUBLE_LINK_LIST_H__
#define __DOUBLE_LINK_LIST_H__

/* 头文件导入区 --------------------------------------------------- */

#include <stdint.h>


#ifdef __cplusplus
extern "C" {
#endif

/** @addtogroup DOUBLE_LINK_LIST
* @brief double link list modules
* @{
*/


/** @defgroup DOUBLE_LINK_LIST_CompilationDefines double link list compilation defines
* @brief 条件编译定义
* @{
*/



/** defgroup DOUBLE_LINK_LIST_CompilationDefines
* @}
*/


/** @defgroup DOUBLE_LINK_LIST_Input_Interface double link list Input API Interface
* @brief 模块输入API接口。即对外部少量依赖模块的API接口
* @{
*/



/** defgroup DOUBLE_LINK_LIST_Input_Interface
* @}
*/


/** @defgroup DOUBLE_LINK_LIST_Exported_MacroDefines double link list exported macro defines
* @brief 全局宏定义
* @{
*/

/* 链表初始化 */
#define DLLIST_INIT(dl) (dl)->head=NULL, (dl)->tail=NULL

/* 定义链表并初始化 */
#define DEFINE_DLLIST(name) DL_LIST name = {0}

/* 获取链表第一个节点的地址 */
#define DL_FIRST_NODE(pdl)  (pdl)->head
/* 获取链表上一个节点的地址 */
#define DL_PREV_NODE(pnode) (pnode)->prev
/* 获取链表下一个节点的地址 */
#define DL_NEXT_NODE(pnode) (pnode)->next
/* 获取链表第一个节点的地址 */
#define DL_LAST_NODE(pdl)   (pdl)->tail

/* 链表遍历 */
#define DL_UP_FOREACH(node, list)   \
            for (node = (list)->tail; node; node = node->prev)
#define DL_DOWN_FOREACH(node, list) \
            for (node = (list)->head; node; node = node->next)
#define DL_FOREACH(node, list, dire) DL_ ## dire ## _FOREACH(node, list)


/** defgroup DOUBLE_LINK_LIST_Exported_MacroDefines
* @}
*/


/** @defgroup DOUBLE_LINK_LIST_Exported_Types double link list exported types
* @brief 全局数据类型声明
* @{
*/

/**
 * 链表返回的负值错误码及其含义
 */
enum dl_err {
    DL_ERR_ARGS     = -1,   /*< 输入参数有误 */
    DL_ERR_NOTEMPTY = -2,   /*< 链表非空*/
    DL_ERR_ISEXIST  = -3,   /*< 节点存在链表中 */
    DL_ERR_NOTEXIST = -4,   /*< 节点不存在链表中 */
    DL_ERR_INDEX    = -5,   /*< 节点索引超出链表范围 */
    DL_ERR_ISEMPTY  = -6,   /*< 链表为空 */
};

/**
 * 链表节点的数据类型
 */
typedef struct dl_node {
    struct dl_node    *next;    /*< 指向下一个节点的指针 */
    struct dl_node    *prev;    /*< 指向上一个节点的指针 */
} DL_NODE;

/**
 * 链表头的数据类型
 */
typedef struct {
    DL_NODE     *head;          /*< 指向链表中头节点的指针 */
    DL_NODE     *tail;          /*< 指向链表中尾节点的指针 */
} DL_LIST;

/**
 * 遍历链表中节点的函数的原型
 *
 * 一般用于打印/查看链表中节点的值。
 *
 * @param [in] node: 指向链表中节点的指针
 */
typedef void (*dl_trav_callback)(const DL_NODE *node);

/**
 * 判断链表中两个节点的大小的函数的原型
 *
 * @param [in] node1: 指向链表中节点的指针
 * @param [in] node2: 指向链表中节点的指针
 * @return 如果节点 node1 和 node2 之间需要交换位置，则返回非0值；否则返回0
 * @note 如果需要对链表进行从小到大排序，那么 node1 大于 node2 就返回非0值；
 *       如果需要对链表进行从大到小排序，那么 node1 小于 node2 就返回非0值。
 */
typedef int32_t (*dl_sort_callback)(const DL_NODE *node1, const DL_NODE *node2);

/**
 * 寻找指定节点的函数的原型
 *
 * @param[in] node: 指向链表中节点的指针
 * @param[in] arg: 用户传入的参数
 * @return 如果找到了指定节点，则返回非0值；否则返回0
 */
typedef int32_t (*dl_match_callback)(const DL_NODE *node, void *arg);


/** defgroup DOUBLE_LINK_LIST_Exported_Types
* @}
*/






/*********************************************************************
                全局变量声明
*********************************************************************/







/*********************************************************************
                全局函数声明
*********************************************************************/

extern void     dllist_static_init(DL_LIST *dl);
extern DL_LIST *dllist_alloc_init(void);
extern int32_t  dllist_free(const DL_LIST *dl);
extern void     dllist_destroy(DL_LIST *dl);
extern int32_t  dllist_destroyCallback(DL_LIST *dl, dl_trav_callback callback);
extern int32_t  dllist_isempty(const DL_LIST *dl);
extern int32_t  dllist_length(const DL_LIST *dl);
extern int32_t  dllist_insert_head(DL_LIST *dl, DL_NODE *node);
extern int32_t  dllist_insert_tail(DL_LIST *dl, DL_NODE *node);
extern int32_t  dllist_insert_at(DL_LIST *dl, DL_NODE *node, uint32_t index);
extern DL_NODE *dllist_at(const DL_LIST *dl, uint32_t index);
extern int32_t  dllist_addr2at(const DL_LIST *dl, const DL_NODE *node);
extern int32_t  dllist_sort(DL_LIST *dl, dl_sort_callback callback);
extern int32_t  dllist_delete(DL_LIST *dl, const DL_NODE *node);
extern DL_NODE *dllist_deleteAt(DL_LIST *dl, uint32_t index);
extern int32_t  dllist_traverse(const DL_LIST *dl, dl_trav_callback callback);
extern DL_NODE *dllist_find(const DL_LIST *dl, dl_match_callback callback,
                            void *arg);








/** addtogroup DOUBLE_LINK_LIST
* @}
*/

#ifdef __cplusplus
}
#endif

#endif // __DOUBLE_LINK_LIST_H__


/***  Copyright (C) 2021 wy1107412334@163.com All rights reserved ***/
/****************************** END OF FILE *************************/

